#ifndef _MIPS_ASM_H
#define _MIPS_ASM_H

#include <regdef.h>

// 如果未定义ABICALLS，则定义ABICALLS为.abicalls
#ifndef ABICALLS
#define	ABICALLS	.abicalls
#endif

// 如果定义了ABICALLS且没有定义_KERNEL，执行ABICALLS
#if defined(ABICALLS) && !defined(_KERNEL)
	ABICALLS
#endif

#define RCSID(x) // 定义版本控制标识

/*
 * 定义如何访问未对齐的数据字
 */
#if defined(__MIPSEL__)
#define LWLO    lwl // 小端字访问低位
#define LWHI    lwr // 小端字访问高位
#define	SWLO	swl // 小端字存储低位
#define	SWHI	swr // 小端字存储高位
#else
#if defined(__MIPSEB__)
#define LWLO    lwr // 大端字访问高位
#define LWHI    lwl // 大端字访问低位
#define	SWLO	swr // 大端字存储高位
#define	SWHI	swl // 大端字存储低位
#else
#error "__MIPSEL__ or __MIPSEB__ must be defined" // 错误提示，必须定义__MIPSEL__或__MIPSEB__
#endif
#endif

/*
 * 如果使用abicalls，则设置gp寄存器的代码。
 */
#if defined(ABICALLS) && !defined(_KERNEL)
#define	ABISETUP		\
	.set	noreorder;	\
	.cpload	t9;		\
	.set	reorder;
#else
#define	ABISETUP // 如果不使用，ABISETUP为空
#endif

/*
 * 定义用于 -pg 代码生成的入口代码
 */
#if defined(GPROF) || defined(PROF)
#define	MCOUNT			\
	subu 	sp, sp, 32;	\
	.cprestore 16;		\
	sw	ra, 28(sp);	\
	sw	gp, 24(sp);	\
	.set	noat;		\
	.set	noreorder;	\
	move	AT, ra;		\
	jal	_mcount;	\
	subu	sp, sp, 8;	\
	lw	ra, 28(sp);	\
	addu	sp, sp, 32;	\
	.set reorder;		\
	.set	at;
#else
#define	MCOUNT // 如果不进行统计，MCOUNT为空
#endif

/*
 * LEAF(x)
 *
 *	声明一个叶子例程。
 */
#define LEAF(x)			\
	.align	3;		\
	.globl x;		\
	.ent x, 0;		\
x: ;				\
	.frame sp, 0, ra;	\
	ABISETUP		\
	MCOUNT

#define	ALEAF(x)		\
	.globl	x;		\
x:

/*
 * NLEAF(x)
 *
 *	声明一个非覆盖的叶子例程。
 */
#define NLEAF(x)		\
	.align	3;		\
	.globl x;		\
	.ent x, 0;		\
x: ;				\
	.frame sp, 0, ra;	\
	ABISETUP

/*
 * NON_LEAF(x)
 *
 *	声明一个非叶子例程（调用其他C函数的例程）。
 */
#define NON_LEAF(x, fsize, retpc) \
	.align	3;		\
	.globl x;		\
	.ent x, 0;		\
x: ;				\
	.frame sp, fsize, retpc; \
	ABISETUP		\
	MCOUNT

/*
 * NNON_LEAF(x)
 *
 *	声明一个非覆盖的非叶子例程
 *	（调用其他C函数的例程）。
 */
#define NNON_LEAF(x, fsize, retpc) \
	.align	3;		\
	.globl x;		\
	.ent x, 0;		\
x: ;				\
	.frame sp, fsize, retpc; \
	ABISETUP

/*
 * END(x)
 *
 *	标记一个过程的结束。
 */
#define END(x) \
	.end x

/*
 * 从汇编语言中进行panic和printf的宏。
 */
#define PANIC(msg) \
	la	a0, 9f; \
	jal	panic; \
	MSG(msg)

#define	PRINTF(msg) \
	la	a0, 9f; \
	jal	printf; \
	MSG(msg)

#define	MSG(msg) \
	.rdata; \
9:	.asciiz	msg; \
	.text

#define ASMSTR(str) \
	.asciiz str; \
	.align	3

// 根据指针大小定义指针操作的宏
#if (_MIPS_SZPTR == 32)
#define PTR_ADD		add
#define PTR_ADDU	addu
#define PTR_ADDI	addi
#define PTR_ADDIU	addiu
#define PTR_SUB		sub
#define PTR_SUBU	subu
#define PTR_L		lw
#define PTR_S		sw
#define PTR_LA		la
#define PTR_LI		li
#define PTR_SLL		sll
#define PTR_SLLV	sllv
#define PTR_SRL		srl
#define PTR_SRLV	srlv
#define PTR_SRA		sra
#define PTR_SRAV	srav

#define PTR_SCALESHIFT	2 // 指针缩放位移

#define PTR		.word // 定义指针类型
#define PTRSIZE		4 // 指针大小
#define PTRLOG		2 // 指针的对数值
#endif

#if (_MIPS_SZPTR == 64) // 处理64位指针的宏
#define PTR_ADD		dadd
#define PTR_ADDU	daddu
#define PTR_ADDI	daddi
#define PTR_ADDIU	daddiu
#define PTR_SUB		dsub
#define PTR_SUBU	dsubu
#define PTR_L		ld
#define PTR_S		sd
#define PTR_LA		dla
#define PTR_LI		dli
#define PTR_SLL		dsll
#define PTR_SLLV	dsllv
#define PTR_SRL		dsrl
#define PTR_SRLV	dsrlv
#define PTR_SRA		dsra
#define PTR_SRAV	dsrav

#define PTR_SCALESHIFT	3 // 指针缩放位移

#define PTR		.dword // 定义指针类型
#define PTRSIZE		8 // 指针大小
#define PTRLOG		3 // 指针的对数值
#endif

#endif /* !_MIPS_ASM_H */
